﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI.WebControls;
using System.Linq;
using System.Linq.Expressions;

namespace Youz.Common.Helper
{
    /// <summary>
    /// 用于验证的公共类
    /// </summary>
    public class ValidationHelper
    {
        #region 判断对象是否为空
        /// <summary>
        /// 判断对象是否为空，为空返回true
        /// </summary>
        /// <typeparam name="T">要验证的对象的类型</typeparam>
        /// <param name="data">要验证的对象</param>        
        public static bool IsNullOrEmpty<T>(T data)
        {
            //如果为null
            if (data == null)
            {
                return true;
            }

            //如果为""
            if (data.GetType() == typeof(String))
            {
                if (string.IsNullOrEmpty(data.ToString().Trim()))
                {
                    return true;
                }
            }

            //如果为DBNull
            if (data.GetType() == typeof(DBNull))
            {
                return true;
            }

            //不为空
            return false;
        }

        /// <summary>
        /// 判断对象是否为空，为空返回true
        /// </summary>
        /// <param name="data">要验证的对象</param>
        public static bool IsNullOrEmpty(object data)
        {
            //如果为null
            if (data == null)
            {
                return true;
            }

            //如果为""
            if (data.GetType() == typeof(String))
            {
                if (string.IsNullOrEmpty(data.ToString().Trim()))
                {
                    return true;
                }
            }

            //如果为DBNull
            if (data.GetType() == typeof(DBNull))
            {
                return true;
            }

            //不为空
            return false;
        }
        #endregion

        public static bool IsMobileNo(string MobileNo)
        {
            if (string.IsNullOrEmpty(MobileNo))
            {
                return false;
            }

            return Regex.IsMatch(MobileNo, @"^1\d{10}$");
        }

        /// <summary>
        /// 验证IP地址是否合法
        /// </summary>
        /// <param name="ip">要验证的IP地址</param>        
        public static bool IsIP(string ip)
        {
            //如果为空，认为验证合格
            if (IsNullOrEmpty(ip))
            {
                return false;
            }

            //清除要验证字符串中的空格
            ip = ip.Trim();

            //模式字符串
            string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";

            //验证
            return Regex.IsMatch(ip, pattern);
        }

        /// <summary>
        /// 验证EMail是否合法
        /// </summary>
        /// <param name="email">要验证的Email</param>
        public static bool IsEmail(string email)
        {
            if (string.IsNullOrEmpty(email))
            {
                return false;
            }

            string pattern = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$";

            return Regex.IsMatch(email.Trim(), pattern);
        }

        /// <summary>
        /// 验证日期是否合法,对不规则的作了简单处理
        /// </summary>
        /// <param name="date">日期</param>
        public static bool IsDate(ref string date)
        {
            //如果为空，认为验证合格
            if (IsNullOrEmpty(date))
            {
                return false;
            }

            //清除要验证字符串中的空格
            date = date.Trim();

            //替换\
            date = date.Replace(@"\", "-");
            //替换/
            date = date.Replace(@"/", "-");

            //如果查找到汉字"今",则认为是当前日期
            if (date.IndexOf("今") != -1)
            {
                date = DateTime.Now.ToString();
            }

            try
            {
                //用转换测试是否为规则的日期字符
                date = Convert.ToDateTime(date).ToString("d");
                return true;
            }
            catch
            {
                //如果日期字符串中存在非数字，则返回false
                if (!IsInt(date))
                {
                    return false;
                }

                #region 对纯数字进行解析
                //对8位纯数字进行解析
                if (date.Length == 8)
                {
                    //获取年月日
                    string year = date.Substring(0, 4);
                    string month = date.Substring(4, 2);
                    string day = date.Substring(6, 2);

                    //验证合法性
                    if (Convert.ToInt32(year) < 1900 || Convert.ToInt32(year) > 2100)
                    {
                        return false;
                    }
                    if (Convert.ToInt32(month) > 12 || Convert.ToInt32(day) > 31)
                    {
                        return false;
                    }

                    //拼接日期
                    date = Convert.ToDateTime(year + "-" + month + "-" + day).ToString("d");
                    return true;
                }

                //对6位纯数字进行解析
                if (date.Length == 6)
                {
                    //获取年月
                    string year = date.Substring(0, 4);
                    string month = date.Substring(4, 2);

                    //验证合法性
                    if (Convert.ToInt32(year) < 1900 || Convert.ToInt32(year) > 2100)
                    {
                        return false;
                    }
                    if (Convert.ToInt32(month) > 12)
                    {
                        return false;
                    }

                    //拼接日期
                    date = Convert.ToDateTime(year + "-" + month).ToString("d");
                    return true;
                }

                //对5位纯数字进行解析
                if (date.Length == 5)
                {
                    //获取年月
                    string year = date.Substring(0, 4);
                    string month = date.Substring(4, 1);

                    //验证合法性
                    if (Convert.ToInt32(year) < 1900 || Convert.ToInt32(year) > 2100)
                    {
                        return false;
                    }

                    //拼接日期
                    date = year + "-" + month;
                    return true;
                }

                //对4位纯数字进行解析
                if (date.Length == 4)
                {
                    //获取年
                    string year = date.Substring(0, 4);

                    //验证合法性
                    if (Convert.ToInt32(year) < 1900 || Convert.ToInt32(year) > 2100)
                    {
                        return false;
                    }

                    //拼接日期
                    date = Convert.ToDateTime(year).ToString("d");
                    return true;
                }
                #endregion

                return false;
            }
        }

        /// <summary>
        /// 验证身份证是否合法
        /// </summary>
        /// <param name="idCard">要验证的身份证</param>        
        public static bool IsIDCardCN(string idCard)
        {
            //如果为空，认为验证合格
            if (IsNullOrEmpty(idCard))
            {
                return false;
            }

            //清除要验证字符串中的空格
            idCard = idCard.Trim();

            //模式字符串
            StringBuilder pattern = new StringBuilder();
            pattern.Append(@"^(11|12|13|14|15|21|22|23|31|32|33|34|35|36|37|41|42|43|44|45|46|");
            pattern.Append(@"50|51|52|53|54|61|62|63|64|65|71|81|82|91)");
            pattern.Append(@"(\d{13}|\d{15}[\dx])$");

            //验证
            return Regex.IsMatch(idCard, pattern.ToString());
        }

        /// <summary>
        /// 判断对象是否为Int32类型的数字
        /// </summary>
        /// <param name="Expression"></param>
        /// <returns></returns>
        public static bool IsNumeric(object Expression)
        {
            if (Expression != null)
            {
                string str = Expression.ToString();
                if (str.Length > 0 && str.Length <= 11 && Regex.IsMatch(str, @"^[-]?[0-9]*[.]?[0-9]*$"))
                {
                    if ((str.Length < 10) || (str.Length == 10 && str[0] == '1') || (str.Length == 11 && str[0] == '-' && str[1] == '1'))
                    {
                        return true;
                    }
                }
            }
            return false;

        }

        public static bool IsDouble(object Expression)
        {
            if (Expression != null)
            {
                return Regex.IsMatch(Expression.ToString(), @"^([0-9])[0-9]*(\.\w*)?$");
            }
            return false;
        }

        public static bool IsAlpha(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-zA-Z]*$");
        }
        public static bool IsAlphaUpperCase(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[A-Z]*$");
        }

        public static bool IsAlphaLowerCase(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-z]*$");
        }

        public static bool IsAlphaNumeric(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-zA-Z0-9]*$");
        }

        public static bool IsAlphaNumericSpace(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-zA-Z0-9 ]*$");
        }

        public static bool IsAlphaNumericSpaceDash(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-zA-Z0-9 \-]*$");
        }

        public static bool IsAlphaNumericSpaceDashUnderscore(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-zA-Z0-9 \-_]*$");
        }

        public static bool IsAlphaNumericSpaceDashUnderscorePeriod(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[a-zA-Z0-9\. \-_]*$");
        }

        #region USA
        public static bool IsZipCodeUS(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"\d{5}");
        }
        public static bool IsZipCodeUSWithFour(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"\d{5}[-]\d{4}");
        }

        public static bool IsZipCodeUSWithFourOptional(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"\d{5}([-]\d{4})?");
        }
        public static bool IsPhoneUS(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"\d{3}[-]?\d{3}[-]?\d{4}");
        }
        #endregion

        /// <summary>
        /// 验证是否为正整数
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsInt(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"^[0-9]*$");
        }

        public static bool IsTime(string timeval)
        {
            if (string.IsNullOrEmpty(timeval))
            {
                return false;
            }

            return Regex.IsMatch(timeval, @"^((([0-1]?[0-9])|(2[0-3])):([0-5]?[0-9])(:[0-5]?[0-9])?)$");
        }

        /// <summary>
        /// 检查是否为空（null 或是""）
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNull(object obj)
        {
            if (obj == null)
            {
                return true;
            }

            string typeName = obj.GetType().Name;
            switch (typeName)
            {
                case "String[]":
                    string[] list = (string[])obj;
                    if (list.Length == 0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                default:
                    string str = obj.ToString();
                    if (str == null || str == "")
                        return true;
                    else
                        return false;
            }
        }

        /// <summary>
        /// 检查是否为空（null 或是""）
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNotNull(object obj)
        {
            return (!IsNull(obj));
        }

        /// <summary>
        /// 判断传入的数字是否为0
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNullZero(object obj)
        {
            return !IsNotNullZero(obj);
        }

        /// <summary>
        /// 判断传入的数字是否不为0
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNotNullZero(object obj)
        {
            if (IsNull(obj))
            {
                return false;
            }
            else
            {
                try
                {
                    double d = Convert.ToDouble(obj);
                    if (d == 0)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 判断是否为日期型变量
        /// </summary>
        /// <param name="str">日期变量</param>
        /// <returns>是否为日期</returns>
        public static bool IsDateTime(string str)
        {
            try
            {
                Convert.ToDateTime(str);

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 判断是否为日期型变量
        /// </summary>
        /// <param name="obj">日期变量</param>
        /// <returns>是否为日期</returns>
        public static bool IsDateTime(object obj)
        {
            try
            {
                Convert.ToDateTime(obj.ToString());

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 判断是否为base64字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsBase64String(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            //A-Z, a-z, 0-9, +, /, =
            return Regex.IsMatch(str, @"[A-Za-z0-9\+\/\=]");
        }

        /// <summary>
        /// 判断文件名是否为浏览器可以直接显示的图片文件名
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns>是否可以直接显示</returns>
        public static bool IsImgFilename(string filename)
        {
            if (string.IsNullOrEmpty(filename))
            {
                return false;
            }

            filename = filename.Trim();
            if (filename.EndsWith(".") || filename.IndexOf(".") == -1)
            {
                return false;
            }
            string extname = filename.Substring(filename.LastIndexOf(".") + 1).ToLower();
            return (extname == "jpg" || extname == "jpeg" || extname == "png" || extname == "bmp" || extname == "gif");
        }

        /// <summary>
        /// 检测是否是正确的Url
        /// </summary>
        /// <param name="strUrl">要验证的Url</param>
        /// <returns>判断结果</returns>
        public static bool IsURL(string strUrl)
        {
            if (string.IsNullOrEmpty(strUrl))
            {
                return false;
            }

            return Regex.IsMatch(strUrl, @"^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{1,10}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
        }

        /// <summary>
        /// 判断字符串是否是yy-mm-dd字符串
        /// </summary>
        /// <param name="str">待判断字符串</param>
        /// <returns>判断结果</returns>
        public static bool IsDateString(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }

            return Regex.IsMatch(str, @"(\d{4})-(\d{1,2})-(\d{1,2})");
        }

        /// <summary>
        /// 判断是否为Unicode码
        /// </summary>
        public static bool IsUnicode(string s)
        {
            string pattern = @"^[\u4E00-\u9FA5\uE815-\uFA29]+$";
            return Regex.IsMatch(s, pattern);
        }

        /// <summary>
        /// 判断一个字符串是否是一个由逗号分隔的数字列表。
        /// </summary>
        /// <param name="str">需要判断的字符串</param>
        /// <returns></returns>
        public static bool IsNumberList(string str)
        {
            return IsNumberList(str, ',');
        }

        /// <summary>
        /// 判断一个字符串是否是一个由指定的字符分隔的数字列表。
        /// </summary>
        /// <param name="str"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static bool IsNumberList(string str, char separator)
        {
            if (null == str)
            {
                return false;
            }
            int len = str.Length;
            if (0 == len)
            {
                return false;
            }
            if (!char.IsNumber(str[0]) || !char.IsNumber(str[len - 1]))
            {
                return false;
            }
            len--;
            for (int i = 1; i < len; i++)
            {
                if (separator == str[i])
                {
                    if (!char.IsNumber(str[i - 1]) || !char.IsNumber(str[i + 1]))
                    {
                        return false;
                    }
                }
                else if (!char.IsNumber(str[i]))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 判断字符串是否由汉字组成
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsChinese(string s)
        {
            string pattern = @"^[\u4e00-\u9fa5]{2,}$";

            return Regex.IsMatch(s, pattern);
        }


        /// <summary>
        /// 判断是否是正整数
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsUnsNumeric(string s)
        {
            string pattern = @"^[0-9]+$";
            return Regex.IsMatch(s, pattern);
        }


        /// <summary>
        /// 判断是否是正浮点数
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsUnsFloat(string s)
        {
            string pattern = @"^[0-9]+.?[0-9]+$";
            return Regex.IsMatch(s, pattern);
        }

        /// <summary>
        /// 判断是否为相对地址（虚拟地址）
        /// </summary>
        public static bool IsRelativePath(string s)
        {
            if (s == null || s == string.Empty)
            {
                return false;
            }
            if (s.StartsWith("/") || s.StartsWith("?"))
            {
                return false;
            }
            if (Regex.IsMatch(s, @"^\s*[a-zA-Z]{1,10}:.*$"))
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 判断是否为绝对地址（物理地址）
        /// </summary>
        public static bool IsPhysicalPath(string s)
        {
            string pattern = @"^\s*[a-zA-Z]:.*$";
            return Regex.IsMatch(s, pattern);
        }

        /// <summary>
        /// 字符串中是否有HTML
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsHasHtml(string s)
        {
            return Regex.IsMatch(s, @"<[^>]*>");
        }

        public static bool IsEnumValue<T>(int v)
        {
            var array = Enum.GetValues(typeof(T));
            foreach (int i in array)
            {
                if (i == v)
                {
                    return true;
                }
            }

            return false;
        }

        public static bool IsAllowedExtension(HttpPostedFile fu, FileExtension[] fileEx)
        {
            var filename = fu.FileName;

            filename = filename.Trim();
            if (filename.EndsWith(".") || filename.IndexOf(".") == -1)
            {
                return false;
            }
            string extname = filename.Substring(filename.LastIndexOf(".") + 1).ToLower();

            if (!fileEx.ToList().Exists(m => m.ToString().ToLower() == extname))
            {
                return false;
            }

            //int fileLen = fu.ContentLength;
            //byte[] imgArray = new byte[fileLen];
            //fu.InputStream.Read(imgArray, 0, fileLen);
            //MemoryStream ms = new MemoryStream(imgArray);
            //System.IO.BinaryReader br = new System.IO.BinaryReader(ms);
            //string fileclass = "";
            //byte buffer;
            //try
            //{
            //    buffer = br.ReadByte();
            //    fileclass = buffer.ToString();
            //    buffer = br.ReadByte();
            //    fileclass += buffer.ToString();
            //}
            //catch
            //{
            //}
            //br.Close();
            //ms.Close();
            ////注意将文件流指针还原
            //fu.InputStream.Position = 0;
            //foreach (FileExtension fe in fileEx)
            //{
            //    if (Int32.Parse(fileclass) == (int)fe)
            //        return true;
            //}

            return true;
        }
    }

    public enum FileExtension
    {
        APK,
        GIF,
        JPG,
        BMP,
        PNG,
        DOC,
        DOCX,
        XLSX,
        JS,
        XLS,
        SWF,
        MID,
        RAR,
        ZIP,
        XML,
        TXT,
        MP3,
        WMA,
        WGT

        // 239187 aspx
        // 117115 cs
        // 119105 js
        // 210187 txt
        //255254 sql 		
        // 7790 exe dll,
        // 8297 rar
        // 6063 xml
        // 6033 html
    }
}
